package com.macro.mall.portal.config.sharding;

import cn.hutool.Hutool;
import cn.hutool.core.util.HashUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.setting.dialect.Props;
import com.macro.mall.common.utils.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

/**
 * 自定义数据库的精确分片算法，根据用户名进行分片
 * @author wwj
 */
@Slf4j
public class StringPreciseDBShardingAlgorithm implements PreciseShardingAlgorithm<String> {


    private final long timestamp = 1664179723804L;

    /**
     * 分库虚拟节点数量
     */
    private static int virtualNodeCount;
    /**
     * 分库虚拟节点范围
     */
    private static String virtualNodeCountRang;

    @Override
    public String doSharding(Collection<String> dbNames, PreciseShardingValue<String> preciseShardingValue) {

        Props props = new Props("application-shardingJDBC.properties");
        virtualNodeCount = props.getInt(ShardingConstant.SHARDING_DATASOURCE_VIRTUAL_NODE_COUNT_MEMBER);
        virtualNodeCountRang = props.getStr(ShardingConstant.SHARDING_DATASOURCE_VIRTUAL_NODE_COUNT_RANG_MEMBER);


        long hash = HashUtil.rsHash(String.valueOf(preciseShardingValue.getValue()));
        // 根据用户名的hash值对《virtualNodeCount》进行取余后，得到余数，余数一定在0，《virtualNodeCount》之间的
        long mod = hash % virtualNodeCount;

        Integer modI = Integer.valueOf(mod + "");
        // 由于获取的字符串的hash值可能存在负数，所以需要需要取其绝对值
        modI = ShardingUtils.getAbsoluteValue(modI);

        Integer physicNode = ShardingUtils.getPhysicNodeByVisualNode(modI, virtualNodeCountRang);

        for (String dbName : dbNames) {
            // todo ： 数据库节点为0-12，则physicNode ==2 ,则endsWith会匹配到2和12的情况
            if (dbName.endsWith(String.valueOf(physicNode))) {
                log.info("logic db :{}", dbName);
                return dbName;
            }
        }
        throw new UnsupportedOperationException();
    }
}
